﻿package extremefx.ui {
	import extremefx.events.EventHandler;
	import extremefx.events.KeyEventArgs;
	import extremefx.events.MouseEventArgs;
	import extremefx.geom.Size;
	import extremefx.ui.styles.UIStates;
	
	import flash.display.Sprite;
	import flash.ui.Keyboard;	

	/**
	 * @author Marcelo Volmaro
	 */
	public class Button extends UIComponent {
		private var _pressed:Boolean;
		private var _oldState:uint;
		private var _label:Label;
		private var _minHeight:uint;
		private var _oldKeyCode:uint;
		private var _mh:ButtonSprite;

		public function Button(pLabel:String = "", pParameters:UIParameters = null) {
			super();

			pParameters = initStyle("Button", pParameters);
			pParameters._parent = this;
			_label = new Label(pLabel, pParameters);

			var vui:Sprite = _visualUI; 
			_mSprite.addChild(_label._visualUI);
			
			_mh = new ButtonSprite(vui);
			_mh.onRollOver.add(_rollOver);
			_mh.onRollOut.add(_rollOut);
			_mh.onReleaseOutside.add(_rollOut);
			_mh.onDragOut.add(_rollOut);
			
			_mh.onPress.add(_press);
			_mh.onDragOver.add(_press);
			
			_mh.onRelease.add(_release);
			
			_width = (_label.size = _label.preferredSize).width + _style.padding.left + _style.padding.right;
	
			//get the height from the bitmap
			_height = _minHeight = _style.getFirstBMPData().height;
			_fheight = true;
			_pressed = false;
			invalidate();
		}
		
		/**
		 * Assigns a keyboard keycode that will fire the "onClick" event. This event will fire only if the container that holds the button it is active.
		 * Pass keycode 0 to remove the key handler
		 */
		public function assignKey(pKeyCode:uint):void {
			KeyHandler.removeKeyHandler(_oldKeyCode, _userKeyDown, _userKeyUp);
			
			if (pKeyCode != 0){
				_oldKeyCode = pKeyCode;
				KeyHandler.addKeyHandler(pKeyCode, _userKeyDown, _userKeyUp);
			}
		}
		
		private function _rollOut(pSender:ButtonSprite, pArgs:MouseEventArgs):void{
			_setView(UIStates.NORMAL);
		}
		
		private function _rollOver(pSender:ButtonSprite, pArgs:MouseEventArgs):void{
			_setView(UIStates.HOVER);
		}
		
		private function _press(pSender:ButtonSprite, pArgs:MouseEventArgs):void{
			focus();
			_setView(UIStates.ACTIVE);
		}
		
		private function _release(pSender:ButtonSprite, pArgs:MouseEventArgs):void{
			_setView(UIStates.NORMAL);
			if (_eOnClick != null) _eOnClick.fire();
		}
		
		private function _userKeyDown(pSKStatus:uint):void {
			if (!_pressOnce && _enabled && parent._containerTabGroup.isActive()){
				_press(null, null);
				_pressOnce = true;
			}
		}
		
		private function _userKeyUp(pSKStatus:uint):void {
			if (_pressOnce && _enabled && parent._containerTabGroup.isActive()){
				_release(null, null);
				_pressOnce = false;
			}
		}
		
		protected override function _keyDownHandler(pSender:KeyHandler, pArgs:KeyEventArgs):void {
			if (pArgs.keyboardEvent.keyCode == Keyboard.SPACE && !_pressOnce){
				_press(null, null);
				_pressOnce = true;
			}
		}
		
		protected override function _keyUpHandler(pSender:KeyHandler, pArgs:KeyEventArgs):void {
			if (pArgs.keyboardEvent.keyCode == Keyboard.SPACE && _pressOnce){
				_release(null, null);
				_pressOnce = false;
			}
		}
		
		private function _setView(pState:uint, pForce:Boolean = false):void{
			pState = _getState(pState);
			
			if (_oldState == pState && !pForce) return;
			_oldState = pState;
			_label.setState(pState);
			
			_setDecoState(pState, _width, _height);
		}
		
		override public function get preferredSize():Size {
			var lh:Size = _label.size;
			lh.width += _style.padding.left + _style.padding.right;
			lh.height = _minHeight;
			return lh;
		}

		override public function get minimumSize():Size {
			return preferredSize;
		}
		
		protected override function _draw():void {
			_mh.enabled = _enabled;
			
			_setView(_oldState, true);
			var lh:Size = _label.size;
			_label.setBounds(int((_width - lh.width)/2), int((_height - lh.height)/2));
		}

		override public function dispose():void {
			if (_disposing) return;
			super.dispose();
			_mh.dispose();
			_label.dispose();
			if (_eOnClick) _eOnClick.dispose();
		}

		private var _eOnClick:EventHandler;
		public function get onClick():EventHandler{
			if (_eOnClick == null) _eOnClick = new EventHandler(this);
			return _eOnClick;
		}
	}
}
